package com.minis.jdbc.datasource;

import com.minis.jdbc.pool.PooledConnection;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.sql.DataSource;

public class PooledDataSource implements DataSource {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private Properties connectionProperties;
    private List<PooledConnection> connections = null;
    private int initialSize = 2;

    // 默认构造函数
    public PooledDataSource() {
    }

    private void initPool () {
        this.connections = new ArrayList<>(initialSize);
        for (int i = 0; i < initialSize; i++) {
            Connection connect = null;
            try {
                connect = DriverManager.getConnection(url, username, password);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            PooledConnection pooledConnection = new PooledConnection(connect, false);
            this.connections.add(pooledConnection);
        }
    }

    @Override
    public Connection getConnection() throws SQLException {
        return getConnectionFromDriver(getUsername(), getPassword());
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return getConnectionFromDriver(username, password);
    }

    // 获取数据库连接
    public PooledConnection getConnectionFromDriver(String username, String password) throws SQLException {
        // 初始化连接池
        if (this.connections == null) {
            initPool();
        }

        // 策略：等待一个有效的连接
        PooledConnection pooledConnection= getAvailableConnection();
        while(pooledConnection == null){
            pooledConnection = getAvailableConnection();
            if(pooledConnection == null){
                try {
                    TimeUnit.MILLISECONDS.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return pooledConnection;
    }

    private PooledConnection getAvailableConnection() throws SQLException{
        for(PooledConnection pooledConnection : this.connections){
            if (!pooledConnection.isActive()){
                pooledConnection.setActive(true);
                return pooledConnection;
            }
        }
        return null;
    }


    // 以下是属性相关的getter和setter
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Properties getConnectionProperties() {
        return connectionProperties;
    }
    public void setConnectionProperties(Properties connectionProperties) {
        this.connectionProperties = connectionProperties;
    }
    // 加载driver类
    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
        try {
            Class.forName(this.driverClassName);
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException("Could not load JDBC driver class [" + driverClassName + "]", ex);
        }
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }
    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }
    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
    @Override
    public void setLogWriter(PrintWriter arg0) throws SQLException {
    }
    @Override
    public void setLoginTimeout(int arg0) throws SQLException {
    }
    @Override
    public boolean isWrapperFor(Class<?> arg0) throws SQLException {
        return false;
    }
    @Override
    public <T> T unwrap(Class<T> arg0) throws SQLException {
        return null;
    }

//    // 数据库连接的建立和释放，是很费资源和时间的
//    @Override
//    public Connection getConnection() throws SQLException {
//        return getConnectionFromDriver(getUsername(), getPassword());
//    }
//
//    @Override
//    public Connection getConnection(String username, String password) throws SQLException {
//        return getConnectionFromDriver(username, password);
//    }
//
//    // 将参数组织成Properties结构，然后拿到实际的数据库连接
//    protected Connection getConnectionFromDriver(String username, String password) throws SQLException {
//        Properties mergedProps = new Properties();
//        Properties connProps = getConnectionProperties();
//        if (connProps != null) {
//            mergedProps.putAll(connProps);
//        }
//        if (username != null) {
//            mergedProps.setProperty("user", username);
//        }
//        if (password != null) {
//            mergedProps.setProperty("password", password);
//        }
//
//        this.connection = getConnectionFromDriverManager(getUrl(),mergedProps);
//        return this.connection;
//    }
//
//    // 通过DriverManager.getConnection()建立实际的连接
//    protected Connection getConnectionFromDriverManager(String url, Properties props) throws SQLException {
//        return DriverManager.getConnection(url, props);
//    }
}
